package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.DmcCsunCameraLocationMapper;
import com.csun.cmny.provider.device.csun.camera.CameraMessageHandler;
import com.csun.cmny.provider.device.csun.camera.entity.CsunCameraData;
import com.csun.cmny.provider.exceptions.DmcBizException;
import com.csun.cmny.provider.model.constant.DeviceConstant;
import com.csun.cmny.provider.model.domain.DmcCsunCameraConfig;
import com.csun.cmny.provider.model.domain.DmcCsunCameraLocation;
import com.csun.cmny.provider.model.domain.DmcDevice;
import com.csun.cmny.provider.model.dto.camera.BindCsunCameraLocationDto;
import com.csun.cmny.provider.model.dto.camera.CsunCameraQueryDto;
import com.csun.cmny.provider.model.dto.propertyManagement.SelectDeviceDataDto;
import com.csun.cmny.provider.model.enums.device.DmcDeviceTypeEnum;
import com.csun.cmny.provider.model.vo.CameraReqVo;
import com.csun.cmny.provider.model.vo.OldmanBedRoomBuildingVo;
import com.csun.cmny.provider.model.vo.RoomBuildingVo;
import com.csun.cmny.provider.model.vo.csuncamera.CsunCameraVo;
import com.csun.cmny.provider.model.vo.device.DmcDeviceVo;
import com.csun.cmny.provider.model.vo.life.DmcDeviceByRoom;
import com.csun.cmny.provider.model.vo.propertyManagement.PropertyDataVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.util.PubUtils;
import com.csun.cmny.util.PublicUtil;
import com.csun.cmny.util.RedisKeyUtil;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-09-02 14:15
 * @Description: the class dmc csun camera location service impl
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DmcCsunCameraLocationServiceImpl extends BaseService<DmcCsunCameraLocation>
        implements DmcCsunCameraLocationService {

    @Resource
    private DmcCsunCameraLocationMapper dmcCsunCameraLocationMapper;
    @Resource
    private DmcDeviceService dmcDeviceService;
    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private OmcRpcService omcRpcService;
    @Resource
    private DmcDeviceAlertService dmcDeviceAlertService;
    @Resource
    private DmcCsunCameraConfigService dmcCsunCameraConfigService;
    @Resource
    private CameraMessageHandler cameraMessageHandler;

    /**
     * query dmc csun camera list with page
     *
     * @param csunCameraQueryDto the csun camera query dto
     *
     * @return the list.
     */
    @Override
    public List<CsunCameraVo> queryListWithPage(CsunCameraQueryDto csunCameraQueryDto) {

        PageHelper.startPage(csunCameraQueryDto.getPageNum(), csunCameraQueryDto.getPageSize());

        return dmcCsunCameraLocationMapper.queryListWithPage(csunCameraQueryDto);
    }

    /**
     * delete dmc csun camera by id
     *
     * @param id the csun camera id
     * @return the int.
     */
    @Override
    public Integer deleteById(Long id) {

        // 1、判断摄像头设备是否存在
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsCsunCameraByDeviceId(id);
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC10068001, id);
        }

        // 2、判断摄像头设备是否绑定
        DmcCsunCameraLocation dmcCsunCameraLocation = dmcCsunCameraLocationMapper.selectByPrimaryKey(id);
        if (PublicUtil.isNotEmpty(dmcCsunCameraLocation)) {
            throw new DmcBizException(ErrorCodeEnum.DMC10068002);
        }

        // 3、删除摄像头设备
        return dmcDeviceService.deleteByKey(id);
    }

    /**
     * bind csun camera and location
     *
     * @param bindCsunCameraLocationDto the bind csun camera location dto
     * @param loginAuthDto              the login auth dto
     * @return the int.
     */
    @Override
    public Integer bind(BindCsunCameraLocationDto bindCsunCameraLocationDto,
                        LoginAuthDto loginAuthDto) {
        // 摄像头Id
        Long deviceId = bindCsunCameraLocationDto.getDeviceId();
        // 绑定类型
        Integer bindType = bindCsunCameraLocationDto.getBindType();
        // 绑定位置
        String location = bindCsunCameraLocationDto.getLocation();
        // 老人姓名
        String oldmanName = bindCsunCameraLocationDto.getOldmanName();
        // 老人Id
        Integer oldmanId = bindCsunCameraLocationDto.getOldmanId();
        // 床位Id
        Integer bedId = bindCsunCameraLocationDto.getBedId();
        // 房间Id
        Integer roomId = bindCsunCameraLocationDto.getRoomId();

        // 1、校验摄像头
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsCsunCameraByDeviceId(deviceId);
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC10068001, deviceId);
        }

        // 2、校验守护佳摄像头是否已经被绑定
        DmcCsunCameraLocation dmcCsunCameraLocation = dmcCsunCameraLocationMapper.selectByPrimaryKey(deviceId);
        if (PublicUtil.isNotEmpty(dmcCsunCameraLocation)) {
            throw new DmcBizException(ErrorCodeEnum.DMC10068004, deviceId);
        }

        // 3、校验守护佳摄像头绑定类型
        Preconditions.checkArgument(!PubUtils.isNull(bindType),
                cmnyMessageSource.getMessage("csun.camera.bind.type.null", null));

        Preconditions.checkArgument(bindType >= 0 && bindType <= 4,
                cmnyMessageSource.getMessage("csun.camera.bind.type.range", null));

        boolean flag = false;

        switch (bindType) {  // 根据绑定类型不同进行校验
            case DeviceConstant.DEVICE_BIND_TYPE_CUSTOM :
                // 4、校验绑定位置
                Preconditions.checkArgument(!PubUtils.isNull(location),
                        cmnyMessageSource.getMessage("csun.camera.bind.location.null", null));

                /**
                 * @date    2020-07-23
                 * @author  chisj
                 * @desc    摄像头绑定自定义位置，下发所在机构的阈值
                 */
                flag = true;

                break;
            case DeviceConstant.DEVICE_BIND_TYPE_OLDMAN :
                Preconditions.checkArgument(!PubUtils.isNull(oldmanId),
                        cmnyMessageSource.getMessage("csun.camera.bind.oldman.id.null", null));
                // 5、校验老人是否存在
                OldmanBedRoomBuildingVo oldmanBedRoomBuildingVo = omcRpcService
                        .queryOldmanBedRoomBuildingByOldmanId(oldmanId);
                if (PublicUtil.isEmpty(oldmanBedRoomBuildingVo)) {
                    // 老人不存在
                    throw new DmcBizException(ErrorCodeEnum.DMC100610062);
                }
                bindCsunCameraLocationDto.setOldmanName(oldmanName);
                break;
            case DeviceConstant.DEVICE_BIND_TYPE_BED :
                // 6、校验床位是否存在
                Preconditions.checkArgument(!PubUtils.isNull(bedId),
                        cmnyMessageSource.getMessage("csun.camera.bind.bed.id.null", null));
                // 校验房间Id是否存在
                OldmanBedRoomBuildingVo bedRoomBuildingVo = omcRpcService
                        .queryOldmanBedRoomBuildingByBedId(bedId);
                if (PublicUtil.isEmpty(bedRoomBuildingVo)) {
                    // 床位不存在
                    throw new DmcBizException(ErrorCodeEnum.DMC100610060);
                }
                break;
                // 7、校验房间是否绑定
            case DeviceConstant.DEVICE_BIND_TYPE_ROOM :
                Preconditions.checkArgument(!PubUtils.isNull(roomId),
                        cmnyMessageSource.getMessage("csun.camera.bind.room.id.null", null));
                // 校验房间Id是否存在
                RoomBuildingVo roomBuildingVo = omcRpcService
                        .queryRoomBuildingByRoomId(roomId);
                if (PublicUtil.isEmpty(roomBuildingVo)) {
                    // 床位不存在
                    throw new DmcBizException(ErrorCodeEnum.DMC100610059);
                }

                flag = true;

                break;
            case DeviceConstant.DEVICE_BIND_TYPE_LIFE :
                Preconditions.checkArgument(!PubUtils.isNull(roomId),
                        cmnyMessageSource.getMessage("csun.camera.bind.room.id.null", null));
                // 校验房间Id是否存在
                // TODO 校验life房间是否存在
                /**
                 * @date    2019-01-07
                 * @author  chisj
                 * @desc    一个房间只能绑定一个摄像头
                 */
                dmcCsunCameraLocation = new DmcCsunCameraLocation();
                dmcCsunCameraLocation.setBindType(DeviceConstant.DEVICE_BIND_TYPE_LIFE);
                dmcCsunCameraLocation.setRoomId(bindCsunCameraLocationDto.getRoomId());
                int count = dmcCsunCameraLocationMapper.selectCount(dmcCsunCameraLocation);
                if (count > 0) {
                    throw new DmcBizException(ErrorCodeEnum.DMC100614007);
                }

                flag = true;

                break;
        }

        // 8、进行绑定
        DmcCsunCameraLocation record = new DmcCsunCameraLocation();
        BeanUtils.copyProperties(bindCsunCameraLocationDto, record);
        record.setCreator(loginAuthDto.getUserName());
        record.setCreatorId(loginAuthDto.getUserId());
        int result = dmcCsunCameraLocationMapper.insertSelective(record);

        // 9、缓存redis
        if (result > 0) {
            // 设置redisKey
            CsunCameraData csunCameraData = new CsunCameraData();
            csunCameraData.setDeviceId(dmcDevice.getId());
            csunCameraData.setDeviceNo(dmcDevice.getDeviceNo());
            csunCameraData.setGroupId(dmcDevice.getGroupId());

            redisTemplate.opsForValue().set(RedisKeyUtil.getCsunCameraKey(dmcDevice.getDeviceNo()),
                    csunCameraData);

            if (flag) {
                /**
                 * @date    2020-04-02
                 * @author  chisj
                 * @desc    下发配置参数
                 */
                // 删除摄像头配置
                DmcCsunCameraConfig dmcCsunCameraConfig = new DmcCsunCameraConfig();
                dmcCsunCameraConfig.setDeviceId(deviceId);
                dmcCsunCameraConfigService.delete(dmcCsunCameraConfig);

                // 根据房间Id和机构Id查询配置
                dmcCsunCameraConfig = dmcCsunCameraConfigService.queryConfigByRoomIdAndGroupId(roomId, loginAuthDto.getGroupId());

                // 下发配置
                if (PublicUtil.isNotEmpty(dmcCsunCameraConfig)) {
                    dmcCsunCameraConfig.setDeviceId(deviceId);
                    dmcCsunCameraConfigService.saveOrUpdate(dmcCsunCameraConfig);

                    cameraMessageHandler.sendCameraConfigMsg(deviceId,
                            dmcCsunCameraConfig.getWalkMeasuringStartTime(),
                            dmcCsunCameraConfig.getWalkMeasuringEndTime(),
                            dmcCsunCameraConfig.getWalkMeasuringTimeInterval(),
                            dmcCsunCameraConfig.getTumbleMeasuringFrame(),
                            dmcCsunCameraConfig.getCameraCheckTime(),
                            dmcCsunCameraConfig.getBeforeDuration(),
                            dmcCsunCameraConfig.getAfterDuration());
                }
            }
        } else {
            throw new DmcBizException(ErrorCodeEnum.DMC100610071);
        }

        return result;
    }

    /**
     * untied csun camera and location
     *
     * @param deviceId the device id
     * @return the int.
     */
    @Override
    public Integer untied(Long deviceId) {

        // 1.判断设备Id是否存在
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsCsunCameraByDeviceId(deviceId);
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC10068001, deviceId);
        }

        // 2.判断摄像头已经绑定
        DmcCsunCameraLocation dmcCsunCameraLocation = dmcCsunCameraLocationMapper
                .selectByPrimaryKey(deviceId);
        if (PublicUtil.isEmpty(dmcCsunCameraLocation)) {
            throw new DmcBizException(ErrorCodeEnum.DMC10068005, deviceId);
        }

        // 3.解绑智能床垫-日创
        Integer result = dmcCsunCameraLocationMapper.deleteByPrimaryKey(deviceId);
        if (result > 0) {
//            if(dmcCsunCameraLocation.getBindType().equals(DeviceConstant.DEVICE_BIND_TYPE_LIFE)){
                // 删除报警记录
                dmcDeviceAlertService.deleteByDeviceId(deviceId);
//            }

            //删除摄像头配置
            dmcCsunCameraConfigService.deleteByKey(deviceId);
            // 删除设备绑定数据
            redisTemplate.delete(RedisKeyUtil.getCsunCameraKey(dmcDevice.getDeviceNo()));
        }
        return result;
    }

    /**
     * get csun camera by device no
     *
     * @param deviceNo the device no
     * @return the csun camera vo
     */
    @Override
    public CsunCameraVo getCsunCameraByDeviceNo(String deviceNo) {

        CsunCameraQueryDto csunCameraQueryDto = new CsunCameraQueryDto();
        csunCameraQueryDto.setDeviceNo(deviceNo);
        csunCameraQueryDto.setDeviceType(DmcDeviceTypeEnum.CSUN_CAMERA.getIndex());

        PageHelper.startPage(1, 1);
        List<CsunCameraVo> csunCameraVoList = dmcCsunCameraLocationMapper.queryListWithPage(csunCameraQueryDto);

        if (PublicUtil.isEmpty(csunCameraVoList)) {
            return null;
        }

        return csunCameraVoList.get(0);
    }

    /**
     * get csun camera by device id
     *
     * @param deviceId the device id
     * @return the csun camera vo
     */
    @Override
    public CsunCameraVo getCsunCameraByDeviceId(Long deviceId) {

        CsunCameraQueryDto csunCameraQueryDto = new CsunCameraQueryDto();
        csunCameraQueryDto.setDeviceId(deviceId);
        csunCameraQueryDto.setDeviceType(DmcDeviceTypeEnum.CSUN_CAMERA.getIndex());

        PageHelper.startPage(1, 1);
        List<CsunCameraVo> csunCameraVoList = dmcCsunCameraLocationMapper.queryListWithPage(csunCameraQueryDto);

        if (PublicUtil.isEmpty(csunCameraVoList)) {
            return null;
        }

        return csunCameraVoList.get(0);
    }

    @Override
    public List<String> getCameraDeviceNoByLifeRoomId(Long roomId) {
        DmcCsunCameraLocation locationQuery = new DmcCsunCameraLocation();
        locationQuery.setRoomId(roomId.intValue());
        List<DmcCsunCameraLocation> cameraLocationList = select(locationQuery);
        List<Long> deviceIdList = cameraLocationList.stream().map(c -> c.getDeviceId()).collect(Collectors.toList());
        List<String> cameraNoList = Lists.newArrayList();
        if(deviceIdList.size() > 0){
            List<DmcDeviceVo> dmcDeviceVos = dmcDeviceService.queryDeviceListByIdList(deviceIdList);
            cameraNoList = dmcDeviceVos.stream().map(d -> d.getDeviceNo()).collect(Collectors.toList());

        }
        return cameraNoList;
    }

    @Override
    public List<Long> selectDeviceIdByRoomId(Long roomId) {
        return dmcCsunCameraLocationMapper.selectDeviceIdByRoomId(roomId);
    }

    @Override
    public DmcDeviceByRoom selectRoomIdByDeviceId(Long alertId) {
        return dmcCsunCameraLocationMapper.selectRoomIdByDeviceId(alertId);
    }

    /**
     * query csun camera bind list
     *
     * @return the csun camera data list
     */
    @Override
    public List<CsunCameraData> queryCsunCameraBindList() {

        return dmcCsunCameraLocationMapper.queryCsunCameraBindList();
    }

    /**
     * 根据房间Id查询摄像头数据
     *
     * @param roomIdList the room id list
     *
     * @return the camera req vo list
     */
    @Override
    public List<CameraReqVo> queryCameraByRoomIds(List<Integer> roomIdList) {

        return dmcCsunCameraLocationMapper.queryCameraByRoomIds(roomIdList);
    }

    @Override
    public List<PropertyDataVo> selectDeviceData(SelectDeviceDataDto selectDeviceDataDto) {
        return dmcCsunCameraLocationMapper.selectDeviceData(selectDeviceDataDto);
    }

}
